package com.roshan.service.impl;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.roshan.dao.UserDAO;
import com.roshan.domain.User;
import com.roshan.service.UserService;
import com.roshan.strategy.UserValidationStrategy;
import com.roshan.util.constants.EntityPropertyConstants;
import com.roshan.util.constants.LoggerMessagesConstants;
import com.roshan.util.constants.NamedQueryConstants;

@Service
public class UserServiceImpl extends BaseServiceImpl<User, Long> implements UserService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserValidationStrategy userValidationStrategy;

    @Autowired
    public void setUserDAO(UserDAO userDAO) {
        this.dao = userDAO;

    }

    @Override
    @Transactional
    public User save(User user) {

        this.userValidationStrategy.validateUser(user);

        String password = user.getSecurityUser().getPassword();
        String encrypttedPassword = this.passwordEncoder.encodePassword(password, null);

        user.getSecurityUser().setPassword(encrypttedPassword);

        return super.save(user);
    }

    @Override
    @Transactional
    public User retrieveUserByUsername(String username, boolean checkInactive) {

        String queryName = NamedQueryConstants.RETRIEVE_ACTIVE_USER_BY_USERNAME;
        if (checkInactive) {
            queryName = NamedQueryConstants.RETRIEVE_USER_BY_USERNAME;
        }

        Map<String, Object> queryParams = new LinkedHashMap<String, Object>();
        queryParams.put(EntityPropertyConstants.USERNAME, username);

        List<User> userList = this.dao.findByNamedQuery(queryName, queryParams);
        if (userList == null || userList.isEmpty()) {
            return null;
        }
        User user = userList.get(0);
        return user;
    }

    @Override
    @Transactional
    public User validatePassword(String username, String password, boolean checkInactive) {

        if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
            this.logger.error(LoggerMessagesConstants.USERNAME_AND_OR_PASSWORD_ARE_IS_EMPTY);
            return null;
        }

        String encrypttedPassword = this.passwordEncoder.encodePassword(password, null);

        String queryName = NamedQueryConstants.VALIDATE_USER;

        Map<String, Object> queryParams = new LinkedHashMap<String, Object>();
        queryParams.put(EntityPropertyConstants.USERNAME, username);
        queryParams.put(EntityPropertyConstants.PASSWORD, encrypttedPassword);
        queryParams.put(EntityPropertyConstants.ACTIVE, Boolean.valueOf(checkInactive));

        List<User> userList = this.dao.findByNamedQuery(queryName, queryParams);
        if (userList == null || userList.isEmpty()) {
            return null;
        }
        User user = userList.get(0);
        return user;
    }

    @Override
    @Transactional
    public User retrieveUser(String userUri) {

        if (!StringUtils.hasText(userUri)) {
            return null;
        }
        String queryName = NamedQueryConstants.RETRIEVE_USER_BY_URI;

        Map<String, Object> queryParams = new LinkedHashMap<String, Object>();
        queryParams.put(EntityPropertyConstants.URI, userUri);

        List<User> userList = this.dao.findByNamedQuery(queryName, queryParams);
        if (userList == null || userList.isEmpty()) {
            return null;
        }
        User user = userList.get(0);
        return user;
    }

}
